#include "random.h"
#include "../core/rng.h"

RandomSampler::RandomSampler(int xstart, int xend, int ystart, int yend, int spp, bool lns, bool ts) : 
				Sampler(xstart, xend, ystart, yend, spp, lns, ts) {
	nSamples = spp;
	xPos = xstart;
	yPos = ystart;
	samplePos = nSamples;
	// Allocate memory for samples
	imageSamples = new Point2[nSamples];
	lensSamples = new Point2[nSamples];
	timeSamples = new float[nSamples];
	
	memset(lensSamples, 0, sizeof(Point2)*nSamples);
	memset(timeSamples, 0, sizeof(float)*nSamples);
	
	// Initialize rng
	rng = new RNG(xstart + ystart * (xend-xstart));
}

RandomSampler::~RandomSampler() {
	SAFE_DELETE_ARRAY(imageSamples);
	SAFE_DELETE_ARRAY(lensSamples);
	SAFE_DELETE_ARRAY(timeSamples);
	SAFE_DELETE(rng);
}

Sampler *RandomSampler::GetSubSampler(int num, int count) {
	int x0, x1, y0, y1;
	ComputeSubWindow(num, count, &x0, &x1, &y0, &y1);
	if (x0 == x1 || y0 == y1) 
		return NULL;
	return new RandomSampler(x0, x1, y0, y1, nSamples, needLensSamples, needTimeSamples);
}

int RandomSampler::GetMoreSamples(Sample *sample) {

	// do this once for a pixel
	if(samplePos == nSamples) {
		
		if(xPos == xPixelEnd || yPos == yPixelEnd)
			return 0;

		// refill samples
		for(int i = 0; i < nSamples; i++) {
			imageSamples[i] = Point2(rng->RandomFloat() + xPos, rng->RandomFloat() + yPos);
			if(needLensSamples)
				lensSamples[i] = Point2(rng->RandomFloat(), rng->RandomFloat());
			if(needTimeSamples)
				timeSamples[i] = rng->RandomFloat();
		}
		// reset sample position to 0;
		samplePos = 0;
		// advance to next column
		xPos++;
		if(xPos == xPixelEnd) {
			// advance to next row
			xPos = xPixelStart;
			yPos++;
		}
	}

	// get samples from sampler
	sample->imageSample = imageSamples[samplePos];
	sample->lensSample = lensSamples[samplePos];
	sample->time = timeSamples[samplePos];

	// fill samples for integrator, do this for every sample
	for(int i = 0; i < sample->n1D.size(); i++) {
		for(int j = 0; j < sample->n1D[i]; j++)
			sample->oneD[i][j] = rng->RandomFloat();
	}
	for(int i = 0; i < sample->n2D.size(); i++) {
		for(int j = 0; j < sample->n2D[i]; j++)
			sample->twoD[i][j] = Point2(rng->RandomFloat(), rng->RandomFloat());
	}

	// advance sample position
	samplePos++;
	
	return 1;
}

